﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CashCommon;
using CashResource;
using Cash.Model;
using Cash;
using CashDriver;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Cash.DialogFroms
{
    public partial class FormNewCash : Form
    {
        public FormNewCash(int registerId)
        {
            InitializeComponent();
            this.RegisterID = registerId;
        }

        #region Свойства

        /// <summary>
        /// Идентификатор чека
        /// </summary>
        public int RegisterID { get; set; }

        #endregion

        #region События

        private void FormNewCash_Load(object sender, EventArgs e)
        {
            if (RegisterID != 0)
            {
                _cashRegister = CashRegister.Instant(this.RegisterID);
                if (_cashRegister.IsPrinted)
                    _frmDecorator = new PrintedForm(_cashRegister, this);
                else
                    _frmDecorator = new EditRelizeForm(_cashRegister, this);

            }
            else if (RegisterID == 0)
            {
                _cashRegister = CashRegister.Instant();
                _frmDecorator = new NewForm(_cashRegister, this);
            }

            btnFind.Text = _findCondition.CaptionCondition;

            _frmDecorator.Actiate();
            _frmDecorator.RefreshForm();
        }
        private void FillTax()
        {
            cbxTax.Items.Clear();
            cbxTax.DisplayMember = "Name";
            cbxTax.Items.AddRange((from t in _tax select new ComboBoxItem(t.F_Taxes, String.Format(FieldsName.CashAccoutnTax1, t.N_Value), t.N_Value)).ToArray());
            cbxTax.SelectedIndex = cbxTax.FindString((from t in _tax where t.D_Date_Begin == _tax.Max(z => z.D_Date_Begin) select String.Format(FieldsName.CashAccoutnTax1, t.N_Value)).ElementAt(0).ToString());
        }
        private void btnFindCash_Click(object sender, EventArgs e)
        {
            //Проверка условий
            if (Tools.AsNullString(tbCashNumber.Text) == "")
                throw new ECashUsers(MessageType.UserMessage, String.Format(CommonError.FieldIsEmpty, lbCashFieldName.Text), "");
            if (dtRegisterDatePrint.Value == null)
                throw new ECashUsers(MessageType.UserMessage, CommonError.FieldDateEmpty, "");

            FormViewCash formViewCash = new FormViewCash(dtRegisterDatePrint.Value, tbCashNumber.Text, _findCondition.CurrentCondition);
            formViewCash.OnResultOk += new DelegateFormResult(formViewCash_OnResultOk);
            formViewCash.ShowDialog();
        }
        private void actionPrint_Execute(object sender, EventArgs e)
        {
            if (Tools.ShowMessage(CommonText.ConfirmPrint) == DialogResult.OK)
            {
                FillCheckFields();
                _cashRegister.PrintCheck();

                if (_cashRegister.IsPrinted)
                {
                    _frmDecorator = new PrintedForm(_cashRegister, this);
                    _frmDecorator.Actiate();
                    _frmDecorator.RefreshForm();
                }
                if (OnCheckPrinted != null)
                    OnCheckPrinted();
                
                this.Close();
            }
        }
        private void actionPreviewPrint_Execute(object sender, EventArgs e)
        {
            try
            {
                // Заполняем поля чека 
                FillCheckFields();

                IPrintDoc printDoc = Builder.PrintDoc(_cashRegister);
                printDoc.PrinPreview(_cashRegister);
            }
            catch(Exception err)
            {
                throw new ECash(MessageType.AllertLog, CommonError.CashPreviewPrintError, err);
            }
        }
        private void FillCheckFields()
        {
            _cashRegister.Name = DriverText.DriverRegisterName;
            _cashRegister.DatePrint = Tools.DateAndCurrentTime(dtRegisterDatePrint.Value);
            _cashRegister.F_Division = _cashRegister.CashAccount.F_Division;
            _cashRegister.F_Subscr = _cashRegister.CashAccount.F_Subscr;
            _cashRegister.Amount = GetCurrentSum();
            if (this.RegisterID == 0 && Tools.IsNullString(tbRegisterNumber.Text))
                _cashRegister.Number = KKM.Inst.CheckNumber;
            else
                try
                {
                    _cashRegister.Number = Convert.ToInt32(tbRegisterNumber.Text, CultureInfo.InvariantCulture);
                }
                catch (Exception err)
                {
                    throw new ECashUsers(MessageType.UserMessage, String.Format(CommonError.NotIntField, label1.Text), err);
                }
            if (cbxTax.SelectedItem != null)
                _cashRegister.N_Tax = ((ComboBoxItem)cbxTax.SelectedItem).Weight;
            else
                _cashRegister.N_Tax = 0;
            _cashRegister.C_Foundation = tbFoundation.Text;
            _cashRegister.Sale_Categories_Name = _cashRegister.CashAccount.Sale_Categories_Name;
            _cashRegister.Sale_Items_Name = _cashRegister.CashAccount.Sale_Items_Name;
            _cashRegister.F_Sale_Categories = _cashRegister.CashAccount.F_Sale_Categories;
            _cashRegister.F_Sale_Items = _cashRegister.CashAccount.F_Sale_Items;
            _cashRegister.AbonentName = tbFromWho.Text;
            _cashRegister.AbonentCode = _cashRegister.CashAccount.Number;
        }
        private void tbCashNumber_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btnFindCash_Click(null, null);
        }
        private void tbAmount_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                Sum_change(tbAmount, null);
        }
        private void btnFind_Click(object sender, EventArgs e)
        {
            _findCondition.NextCondition();
            btnFind.Text = _findCondition.CaptionCondition;
        }

        #endregion

        #region Helper

        private void formViewCash_OnResultOk(int id)
        {
            CashAccount cashAccount = CashAccount.Instant(id);
            if (cashAccount != null)
            {
                _cashRegister.InitFromAccount(cashAccount);

                if (_cashRegister.CashAccount.N_Releaze == 1)
                    _frmDecorator = new EditRelizeForm(_cashRegister, this);
                else
                    _frmDecorator = new EditNotRelizeForm(_cashRegister, this);
                _frmDecorator.Actiate();
                _frmDecorator.RefreshForm();
            }

        }

        private void Sum_change(object sender, EventArgs e)
        {
            if (((Control)sender).Text.Trim() == "")
                return;
            try
            {
                double sum = GetCurrentSum();

                PayNDS payNds = Tools.GetTax(sum, ((ComboBoxItem)cbxTax.SelectedItem).Weight);
                dgvState.Rows[0].Cells[1].Value = payNds.Value.ToString("C");
                dgvState.Rows[1].Cells[1].Value = payNds.Tax.ToString("C");
                tbAmount.Text = sum.ToString("C");
            }
            catch
            {
                throw new ECashUsers(MessageType.UserMessage, String.Format(CommonError.ConvertToDoubleError, lblSum.Text), "");
            }
        }
        private double GetCurrentSum()
        {
            if (tbAmount.Text.Last() == '.')
                tbAmount.Text = tbAmount.Text.Substring(0, tbAmount.Text.Length - 1);
            return Convert.ToDouble(Regex.Replace(tbAmount.Text.Replace('.', ','), @"[^,^\-\d]", ""), CultureInfo.CurrentCulture);
        }

        #endregion

        #region Fields

        CashRegister _cashRegister;
        List<Taxes> _tax = Taxes.Tax;
        FindCondition _findCondition = new FindCondition();
//        FrmProgress _frmProgress;
        FormDecorator _frmDecorator;

        #endregion

        //Events
        public event DlegateWithoutParams OnCheckPrinted;

        #region Added Classes

        /// <summary>
        /// Реализует функционал "револьверного" переключения условия поиска счета (по коду, по имени, по номеру счета)
        /// </summary>
        public class FindCondition
        {
            
            public FindCondition()
            {
                CurrentCondition = FindConditions.Code;
            }

            public FindConditions CurrentCondition { get; set; }
            public void NextCondition()
            {
                switch (CurrentCondition)
                {
                    case FindConditions.Code:
                        CurrentCondition = FindConditions.Name;
                        break;
                    case FindConditions.Name:
                        CurrentCondition = FindConditions.Order;
                        break;
                    case FindConditions.Order:
                        CurrentCondition = FindConditions.Code;
                        break;
                    default:
                        CurrentCondition = FindConditions.Name;
                        break;
                }
            }
            public string CaptionCondition
            {
                get
                {
                    switch (CurrentCondition)
                    {
                        case FindConditions.Code:
                            return CommonText.FindConditionCode;
                        case FindConditions.Name:
                            return CommonText.FindConditionName;
                        case FindConditions.Order:
                            return CommonText.FindConditionOrder;
                        default:
                            return CommonText.FindConditionCode;
                    }
                }
            }
            
        }
        public enum FindConditions { Code, Name, Order };

        private class FormDecorator
        {
            protected FormDecorator(CashRegister cashRegister, FormNewCash formNewCash)
            {
                this._cashRegister = cashRegister;
                this._formNewCash = formNewCash;
            }
            
            public virtual void Actiate() { }
            public virtual void RefreshForm() { }

            protected void FillRealizeCash()
            {
                _formNewCash.dgvContracts.Columns.Clear();
                _formNewCash.dgvState.Columns.Clear();

                // Заполняется таблица договор/вид договора
                _formNewCash.dgvContracts.ColumnCount = 2;
                _formNewCash.dgvContracts.Columns[0].Name = FieldsName.CashAccountName;
                _formNewCash.dgvContracts.Columns[1].Name = FieldsName.CashAccountCategoryName;
                string[] row0 = { _cashRegister.OrderNumber.ToString(), _cashRegister.Sale_Categories_Name};
                _formNewCash.dgvContracts.Rows.Add(row0);

                //Заполняестся таблица Статья/Сумма
                _formNewCash.dgvState.ColumnCount = 2;
                _formNewCash.dgvState.Columns[0].Name = FieldsName.CashAccountState;
                _formNewCash.dgvState.Columns[1].Name = FieldsName.CashAccountMoney;

                PayNDS payNDS = Tools.GetTax(_cashRegister.Amount, _cashRegister.N_Tax);

                string[] row1 = { _cashRegister.Sale_Items_Name, payNDS.Value.ToString("C") };
                string[] row2 = { FieldsName.CashAccountTax, payNDS.Tax.ToString("C") };
                _formNewCash.dgvState.Rows.Add(row1);
                _formNewCash.dgvState.Rows.Add(row2);
            }
            protected void FillNotRealizeCash()
            {
                _formNewCash.dgvContracts.Columns.Clear();
                _formNewCash.dgvState.Columns.Clear();

                // Заполняется таблица договор/вид договора
                _formNewCash.dgvContracts.ColumnCount = 2;
                _formNewCash.dgvContracts.Columns[0].Name = FieldsName.CashAccountName;
                _formNewCash.dgvContracts.Columns[1].Name = FieldsName.CashAccountCategoryName;
                string[] row0 = { _cashRegister.OrderNumber.ToString(), _cashRegister.Sale_Categories_Name };
                _formNewCash.dgvContracts.Rows.Add(row0);

                //Заполняестся таблица Статья/Сумма
                _formNewCash.dgvState.ColumnCount = 2;
                _formNewCash.dgvState.Columns[0].Name = FieldsName.CashAccountState;
                _formNewCash.dgvState.Columns[1].Name = FieldsName.CashAccountMoney;

                string[] row1 = { _cashRegister.Sale_Items_Name, _cashRegister.Amount.ToString("C") };
                _formNewCash.dgvState.Rows.Add(row1);
            }

            protected CashRegister _cashRegister;
            protected FormNewCash _formNewCash;
        }
        private class NewForm : FormDecorator
        {
            public NewForm(CashRegister cashRegister, FormNewCash formNewCash) :
                base(cashRegister, formNewCash) { }

            public override void Actiate()
            {
                base.Actiate();
                base._formNewCash.dtRegisterDatePrint.Value = Tools.DateAndCurrentTime(DateTime.Now);
                _cashRegister.CreatedEmployer = CashEmployer.Inst.C_FIO;
                base._formNewCash.Text = String.Format(CommonText.RegisterFormTitle, CommonText.NewRegisterTitle);

            }
            public override void RefreshForm()
            {
                base.RefreshForm();
                string[] enabledControl = {
                                              "btnFind", 
                                              "tbCashNumber", 
                                              "btnFindCash"
                                          };
                foreach (Control control in base._formNewCash.Controls)
                    control.Enabled = enabledControl.Contains(control.Name) ? true : false;
            }
        }
        private class EditRelizeForm : FormDecorator
        { 
            public  EditRelizeForm(CashRegister cashRegister, FormNewCash formNewCash) : 
                base(cashRegister, formNewCash){}

            public override void Actiate()
            {
                base.Actiate();
                if (base._cashRegister != null)
                    {
                        base._formNewCash.tbRegisterNumber.Text = _cashRegister.Number.ToString();
                        base._formNewCash.tbCashNumber.Text = _cashRegister.AbonentCode;
                        base._formNewCash.tbSubscr.Text = _cashRegister.AbonentName;
                        base._formNewCash.Text = _cashRegister.AbonentName;
                        base._formNewCash.FillTax();
                        base._formNewCash.tbAmount.Text = _cashRegister.Amount.ToString("C");
                        base._formNewCash.tbFromWho.Text = _cashRegister.AbonentName;
                        base._formNewCash.tbFoundation.Text = _cashRegister.C_Foundation;

                        base.FillRealizeCash();
                        base._formNewCash.Text = String.Format(CommonText.RegisterFormTitle, _cashRegister.Number.ToString());
                    }
                }
            public override void RefreshForm()
            {
                base.RefreshForm();
                bool NotPrinted = !_cashRegister.IsPrinted;
                bool hasAccount = _cashRegister.CashAccount != null;

                string[] notEnabledControl = {
                                                 "tbEmployersNumber",
                                                 "tbSubscr"
                                             };
                foreach (Control control in this._formNewCash.Controls)
                    control.Enabled = notEnabledControl.Contains(control.Name) ? false : true;

                base._formNewCash.tbRegisterNumber.Enabled = Properties.Settings.Default.WithoutKKM == 1;

                base._formNewCash.actionPrint.Enabled = NotPrinted && hasAccount;
                base._formNewCash.actionPreviewPrint.Enabled = hasAccount;
            }

            }
        private class EditNotRelizeForm : FormDecorator
        {
            public EditNotRelizeForm(CashRegister cashRegister, FormNewCash formNewCash) :
                base(cashRegister, formNewCash) { }

            public override void Actiate()
            {
                base.Actiate();
                if (base._cashRegister != null)
                {
                    base._formNewCash.cbxTax.Items.Clear();
                    base._formNewCash.tbRegisterNumber.Text = _cashRegister.Number.ToString();
                    base._formNewCash.tbCashNumber.Text = _cashRegister.AbonentCode;
                    base._formNewCash.tbSubscr.Text = _cashRegister.AbonentName;
                    base._formNewCash.Text = _cashRegister.AbonentName;
                    base._formNewCash.tbAmount.Text = _cashRegister.Amount.ToString("C");
                    base._formNewCash.tbFromWho.Text = _cashRegister.AbonentName;
                    base._formNewCash.tbFoundation.Text = _cashRegister.C_Foundation;

                    base.FillNotRealizeCash();
                    base._formNewCash.Text = String.Format(CommonText.RegisterFormTitle, _cashRegister.Number.ToString());
                }
            }
            public override void RefreshForm()
            {
                base.RefreshForm();
                bool NotPrinted = !_cashRegister.IsPrinted;
                bool hasAccount = _cashRegister.CashAccount != null;

                string[] notEnabledControl = {
                                                 "tbEmployersNumber",
                                                 "tbSubscr",
                                                 "cbxTax"
                                             };
                foreach (Control control in this._formNewCash.Controls)
                    control.Enabled = notEnabledControl.Contains(control.Name) ? false : true;

                base._formNewCash.tbRegisterNumber.Enabled = Properties.Settings.Default.WithoutKKM == 1;

                base._formNewCash.actionPrint.Enabled = NotPrinted && hasAccount;
                base._formNewCash.actionPreviewPrint.Enabled = hasAccount;

            }
        }
        private class PrintedForm : FormDecorator
        {
            public  PrintedForm(CashRegister cashRegister, FormNewCash formNewCash) : 
                base(cashRegister, formNewCash){}

            public override void Actiate()
            {
                base.Actiate();
                base._formNewCash.tbRegisterNumber.Text = _cashRegister.Number.ToString();
                base._formNewCash.tbCashNumber.Text = _cashRegister.AbonentCode;
                base._formNewCash.dtRegisterDatePrint.Value = _cashRegister.DatePrint;
                base._formNewCash.tbSubscr.Text = _cashRegister.AbonentName;
                base._formNewCash.Text = _cashRegister.AbonentName;
                base._formNewCash.tbAmount.Text = _cashRegister.Amount.ToString("C");
                base._formNewCash.tbFromWho.Text = _cashRegister.AbonentName;
                base._formNewCash.tbFoundation.Text = _cashRegister.C_Foundation;

                if (base._cashRegister.N_Releaze == 1)
                {
                    base._formNewCash.FillTax();
                    base.FillRealizeCash();
                }
                else
                    base.FillNotRealizeCash();
                base._formNewCash.Text = String.Format(CommonText.RegisterFormTitle, _cashRegister.Number.ToString());
             }
            public override void RefreshForm()
            {
                base.RefreshForm();
                string[] enabledControl = {
                                                 "tsFormDocuments"
                                             };

                foreach (Control control in this._formNewCash.Controls)
                    control.Enabled = enabledControl.Contains(control.Name) ? true : false;

                base._formNewCash.actionPrint.Enabled = false;
                base._formNewCash.actionPreviewPrint.Enabled = true;
                
            }
        }
        
        #endregion
    }
}
